package Dm

import (
	"fmt"
	"db2s/ETL"
	"db2s/global"
	"strings"
)

func (or TableInfoMeta) PackageExist(s global.TablesMetaInfoInput) (result global.ObjectExistReturnResult, err error) {
	var f1 any
	var event = "[oraclePackageExist]"
	for _, v := range []string{
		//"USER_OBJECTS",
		"ALL_OBJECTS",
		"DBA_OBJECTS",
	} {
		result.BaseResult.Sql = fmt.Sprintf("select count(1) as \"sum\" from %v where OBJECT_TYPE = 'PACKAGE' AND STATUS != 'INVALID' and OWNER = '%v' and OBJECT_NAME='%v'", v, s.TableInfo.Schema, s.TableInfo.Table)
		if result.BaseResult.TimeOut, f1, err = ExecSelectSql(ExecSqlInputS{
			Ss:           s,
			Event:        event,
			SelectSqlStr: result.BaseResult.Sql,
			Expect:       ETL.Map,
		}); err != nil || f1 == nil {
			continue
		}
		if fmt.Sprintf("%v", f1.(map[string]any)["sum"]) == "1" {
			result.Result = true
		}
		break
	}
	return
}

func (or TableInfoMeta) PackageName(s global.TablesMetaInfoInput) (result global.ObjectNameReturnResult, err error) {
	var f1 any
	var event = "[oraclePackageName]"
	for _, v := range []string{
		//"USER_OBJECTS",
		"ALL_OBJECTS",
		"DBA_OBJECTS",
	} {
		result.BaseResult.Sql = fmt.Sprintf("select OBJECT_NAME from %v where  OBJECT_TYPE = 'PACKAGE' AND STATUS != 'INVALID' AND OWNER ='%v' %v",
			v, s.TableInfo.Schema, func() string {
				switch {
				case s.TableInfo.Table == "*":
					return ""
				case strings.Contains(s.TableInfo.Table, "%"):
					return fmt.Sprintf(" and OBJECT_NAME like '%%%v%%'", s.TableInfo.Table)
				default:
					return fmt.Sprintf(" and OBJECT_NAME = '%v'", s.TableInfo.Table)
				}
			}())
		if result.BaseResult.TimeOut, f1, err = ExecSelectSql(ExecSqlInputS{
			Ss:           s,
			Event:        event,
			SelectSqlStr: result.BaseResult.Sql,
			Expect:       ETL.StringGarth,
		}); err != nil || f1 == nil {
			continue
		}
		result.Result = f1.([]string)
		break
	}

	return
}
func packagePrintInfo(x *global.PackageResultDefinition) (res string) {
	/*
		-- 包规范
		CREATE OR REPLACE PACKAGE my_package AS
			g_message VARCHAR2(100);
			PROCEDURE my_procedure(param1 IN NUMBER);
			FUNCTION my_function(param1 IN NUMBER) RETURN VARCHAR2;
		END my_package;
		/

		-- 包体
		CREATE OR REPLACE PACKAGE BODY my_package AS
			PROCEDURE my_procedure(param1 IN NUMBER) IS
			BEGIN
				g_message := 'The number is: ' || param1;
				DBMS_OUTPUT.PUT_LINE(g_message);
			END my_procedure;

			FUNCTION my_function(param1 IN NUMBER) RETURN VARCHAR2 IS
			BEGIN
				RETURN 'The function received: ' || param1;
			END my_function;
		END my_package;
		/
	*/
	return fmt.Sprintf("CREATE OR REPLACE %v\n"+
		"CREATE OR REPLACE %v\n"+
		"/", x.HeadText, x.BodyText,
	)
}
func packageDefinitionConvert(x global.PackageResultDefinition) (convert global.PackageDefinitionConvertS) {
	convert = global.PackageDefinitionConvertS{
		Schema:      x.Schema,
		Name:        x.Name,
		Permissions: x.Permissions,
		HeadText:    x.HeadText,
		BodyText:    x.BodyText,
		Comment:     x.Comment,
		PInput:      x.PInput,
		POutput:     x.POutput,
		Type:        x.Type,
		PrintInfo:   x.PrintInfo,
	}
	return
}
func getPackageBody(s global.SchemaObjectInput) (res string, err error) {
	var (
		f1    any
		r     []string
		event = "[oracleGetPackageBody]"
	)
	for _, v := range []string{
		//"USER_source",
		"all_source",
		"dba_source",
	} {
		sqlStr := fmt.Sprintf("SELECT\n"+
			"\"TEXT\" AS \"text\"\n"+
			"FROM\n"+
			"\t\t%v where 1=1\n"+
			"\t\tAND TYPE = 'PACKAGE BODY'\n"+
			"\t\tAND OWNER='%v'\n"+
			"\t\tAND NAME='%v' ORDER BY LINE", v, s.Schema, s.Table)
		if _, f1, err = ExecSelectSql(ExecSqlInputS{
			Ss:           s,
			Event:        event,
			SelectSqlStr: sqlStr,
			Expect:       ETL.SMap,
		}); err != nil || f1 == nil {
			continue
		}
		for _, p := range f1.([]map[string]any) {
			r = append(r, fmt.Sprintf("%v", p["text"]))
		}
		res = strings.Join(r, "")
		break
	}

	return
}
func getPackageHead(s global.SchemaObjectInput) (res string, err error) {
	var (
		f1    any
		r     []string
		event = "[oracleGetPackageHead]"
	)
	for _, v := range []string{
		//"USER_source",
		"all_source",
		"dba_source",
	} {
		sqlStr := fmt.Sprintf("SELECT\n"+
			"\"TEXT\" AS \"text\"\n"+
			"FROM\n"+
			"\t\t%v where 1=1\n"+
			"\t\tAND TYPE = 'PACKAGE'\n"+
			"\t\tAND OWNER='%v'\n"+
			"\t\tAND NAME='%v' ORDER BY LINE", v, s.Schema, s.Table)
		if _, f1, err = ExecSelectSql(ExecSqlInputS{
			Ss:           s,
			Event:        event,
			SelectSqlStr: sqlStr,
			Expect:       ETL.SMap,
		}); err != nil || f1 == nil {
			continue
		}
		for _, p := range f1.([]map[string]any) {
			r = append(r, fmt.Sprintf("%v", p["text"]))
		}
		res = strings.Join(r, "")
		break
	}
	return
}
func (or SchemaObjectMeta) Package(s global.SchemaObjectInput) (result global.SchemaObjectReturnResult, err error) {
	var (
		x global.PackageResultDefinition
	)
	x.Schema = s.Schema
	x.Name = s.Table
	if x.HeadText, err = getPackageHead(s); err != nil {
		return
	}
	if x.BodyText, err = getPackageBody(s); err != nil {
		return
	}
	x.Type = "package"
	x.PrintInfo = packagePrintInfo(&x)
	result.PackageResult.Definition = x
	result.PackageResult.Convert = packageDefinitionConvert(x)
	return
}
